package fr.umlv.m2.uwp2011.service.user;

import java.util.List;

import javax.naming.AuthenticationException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;

import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;

import fr.umlv.m2.uwp2011.service.user.UserDTO.Status;

public class LDAPUserDAO implements UserDAO {
	private LdapTemplate ldapTemplate;
	
	public LDAPUserDAO(LdapTemplate myLdapTemplate) {
		this.ldapTemplate = myLdapTemplate;
	}

	public void setLdapTemplate(LdapTemplate ldapTemplate) {
		this.ldapTemplate = ldapTemplate;
	}

	private UserDTO getUserDetailsAux(String status, AndFilter andFilter, AttributesMapper mapper){
		@SuppressWarnings("unchecked")
		List<UserDTO> list = ldapTemplate.search("ou="+ status + ",ou=users", andFilter.encode(), mapper);
		if(list.size() != 0){
			return list.get(0);
		}else return null;
	}

	@Override
	public UserDTO getUserDetails(String login, String password) throws AuthenticationException {
		AndFilter andFilter = new AndFilter();
		andFilter.and(new EqualsFilter("objectclass", "person"));
		andFilter.and(new EqualsFilter("uid", login));
		andFilter.and(new EqualsFilter("userPassword", password));
		AttributesMapper mapper = new UserAttributeMapper();
		UserDTO userDto = null;
		String[] status = {"student" , "teacher" , "admin"};
		for(String s : status){
			userDto = getUserDetailsAux(s, andFilter, mapper);
			if(userDto != null){
				userDto.setStatus(Status.selectStatus(s));
				return userDto;
			}
		}throw new AuthenticationException("invalid login or password");
	}
	
	private Attributes buildAttributes(UserDTO userDTO){
		Attributes personAttributes = new BasicAttributes();
		BasicAttribute personBasicAttribute = new BasicAttribute("objectclass");
		personBasicAttribute.add("inetOrgPerson");
		personAttributes.put(personBasicAttribute);
		personAttributes.put("uid", userDTO.getLogin());
		personAttributes.put("givenname", userDTO.getGivenName());
		personAttributes.put("sn", userDTO.getLastName());
		personAttributes.put("cn",
				userDTO.getGivenName() + " " + userDTO.getLastName());
		personAttributes.put("userPassword", userDTO.getPassword());
		personAttributes.put("mail", userDTO.getMail());
		return personAttributes;
	}
	
	private DistinguishedName builDistinguishedName(UserDTO userDTO){
		DistinguishedName newContactDN = new DistinguishedName(
				buildDistinguishedName(userDTO.getStatus().getLabel()));
		newContactDN.add("uid", userDTO.getLogin());
		return newContactDN;
	}
	
	@Override
	public void insertUser(UserDTO userDTO) {
		ldapTemplate.bind(builDistinguishedName(userDTO), null, buildAttributes(userDTO));
	}
	
	@Override
	public void updateUser(UserDTO userDTO) {
		ldapTemplate.rebind(builDistinguishedName(userDTO), null, buildAttributes(userDTO));
	}

	@Override
	public void deleteUser(UserDTO userDTO) {
		ldapTemplate.unbind(builDistinguishedName(userDTO));
	}

	private String buildDistinguishedName(String label) {
		return "ou=" + label + ",ou=users";
	}

}
